﻿
#ifndef VULKAN_APP
#define VULKAN_APP
#include "base.h"
#include <vector>
#ifdef __APPLE__
#define VK_USE_PLATFORM_MACOS_MVK
#endif
#ifdef _WIN32
#define VK_USE_PLATFORM_WIN32_KHR
#endif
#include "vulkan/vulkan.h"
#include "SDL2/SDL.h"
XBWUC_BEGAN
// 设备队列信息
struct DeviceQueueInfo
{
	VkQueue queue;
	uint32_t index;
};
struct SDLWindow
{
	SDL_Window *window = nullptr;
	SDL_Renderer *render = nullptr;
};
/**
 * 交换链信息
 */
class SwapChainCheckInfo
{
public:
	//
	VkSurfaceCapabilitiesKHR capability;

	VkSurfaceFormatKHR *surfaceFormat;
	VkPresentModeKHR presentModelKHR;
	// 选择正确的surface
	void choiceRightSurfaceFormatKHR(std::vector<VkSurfaceFormatKHR> &surfaceFormats)
	{
		if (surfaceFormats.size() > 0)
		{
			surfaceFormat = new VkSurfaceFormatKHR();
			for (auto &format : surfaceFormats)
			{
				if (format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR &&
					format.format == VK_FORMAT_B8G8R8A8_SRGB)
				{
					memcpy(surfaceFormat, &format, sizeof(VkSurfaceFormatKHR));
					return;
				}
			}
		}
	};
	void choiceRightPersentModeKHR(std::vector<VkPresentModeKHR> &persentModes)
	{
		if (persentModes.size() > 0)
		{
			for (auto &persentMode : persentModes)
			{
				if (persentMode == VK_PRESENT_MODE_MAILBOX_KHR)
				{
					presentModelKHR = persentMode;
					return;
				}
			}
		}
		presentModelKHR = VK_PRESENT_MODE_FIFO_KHR;
	}
	~SwapChainCheckInfo()
	{
		if (surfaceFormat)
		{
			delete surfaceFormat;
			surfaceFormat = nullptr;
		}
	}
};
class VulkanApplication
{
public:
	VulkanApplication();
	void mainLoop();
	~VulkanApplication();

private:
	static const int DEFAULT_HEIGHT = 800;
	static const int DEFAULT_WIDTH = 1000;
	void freeResource();
	void createsurface();
	void initVulkan();
	void initWindow();
	// ѡ��ͼ�ο�
	void choiceGraphCard();
	// �����߼��豸
	void createLogicDevice();
	// ����������
	void createSwapChain();
	VkShaderModule createShaderModule(const std::vector<char> &code);
	void createImageView();

	void createRenderPass();
	// ����ͼ�ι���
	void createGraphicsPipeline();
	void createVertexBuffer();
    void createFrameBuffer();
    void createCommandPool();
    void createCommandBuffer();

    void recordCommandBuffer(VkCommandBuffer &commandBuffer, uint32_t &imageIndex);
	/**
     * 在主线循环中绘制每一帧。
    */
	void drawFrame();
	/**
	 * 创建同步对象
	 * 
	*/
	void createSyncObject();
	// 窗口管理
	SDLWindow swindow;
	//
	VkPhysicalDevice vkPhysicalDevice;
	VkInstance vkInstance;
	VkSurfaceKHR vksurface;
	VkDevice vkDevice;
	DeviceQueueInfo graphQueue;
	SwapChainCheckInfo swapChainInfo;
	// 交换链
	VkSwapchainKHR vkSwapchainKHR;
	std::vector<VkImage> vkimages;
	std::vector<VkImageView> vkImageViews;
	VkRenderPass vkRenderPass;
	VkPipelineLayout pipelineLayout;
	VkPipeline vkPipeline;
	//顶点缓冲区
	VkBuffer vertexBuffer;
	VkDeviceMemory deviceMemory;
	//重新创建交换链
	void reCreateSwapChain();
	//清楚交换链资源
	void cleanupSwapChain() ;

	uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
	std::vector<VkFence> inFlathFences;
	// 用于同步交换连图片的获取
	std::vector<VkSemaphore> swapchainSemphores;
	// 用于同步每一帧正常渲染
	std::vector<VkSemaphore> renderFinSheamphores;

	std::vector<VkFramebuffer> framebuffers;
	VkCommandPool vkCommandPool;
	std::vector<VkCommandBuffer> vkCommandBuffers;
};
XBWUC_END
#endif
